#include "stdafx.h"
#include <stdio.h>
#include "gtest/gtest.h"
#include "MathTest.h"

using namespace rs;


class Vector3Test : public MathTest
{
};


TEST_F(Vector3Test, ctor)
{
	// Vector3(f32, f32, f32)
	const Vector3 v0(x0, y0, z0);
	EXPECT_FLOAT_EQ(x0, v0.getX());
	EXPECT_FLOAT_EQ(y0, v0.getY());
	EXPECT_FLOAT_EQ(z0, v0.getZ());

	// Vector3(const Vector3&)
	const Vector3 v1 = v0;
	EXPECT_FLOAT_EQ(v0.getX(), v1.getX());
	EXPECT_FLOAT_EQ(v0.getY(), v1.getY());
	EXPECT_FLOAT_EQ(v0.getZ(), v1.getZ());

	// operator =
	Vector3 v2;
	v2 = v0;
	EXPECT_FLOAT_EQ(v0.getX(), v2.getX());
	EXPECT_FLOAT_EQ(v0.getY(), v2.getY());
	EXPECT_FLOAT_EQ(v0.getZ(), v2.getZ());
}


TEST_F(Vector3Test, add)
{
	const Vector3 v0(x0, y0, z0);
	const Vector3 v1(x1, y1, z1);
	Vector3 v;

	// operator +=
	v = v0;
	v += v1;
	EXPECT_FLOAT_EQ(x0+x1, v.getX());
	EXPECT_FLOAT_EQ(y0+y1, v.getY());
	EXPECT_FLOAT_EQ(z0+z1, v.getZ());

	// operator +
	v = v0 + v1;
	EXPECT_FLOAT_EQ(x0+x1, v.getX());
	EXPECT_FLOAT_EQ(y0+y1, v.getY());
	EXPECT_FLOAT_EQ(z0+z1, v.getZ());
}


TEST_F(Vector3Test, sub)
{
	const Vector3 v0(x0, y0, z0);
	const Vector3 v1(x1, y1, z1);
	Vector3 v;

	// operator -=
	v = v0;
	v -= v1;
	EXPECT_FLOAT_EQ(x0-x1, v.getX());
	EXPECT_FLOAT_EQ(y0-y1, v.getY());
	EXPECT_FLOAT_EQ(z0-z1, v.getZ());

	// operator -
	v = v0 - v1;
	EXPECT_FLOAT_EQ(x0-x1, v.getX());
	EXPECT_FLOAT_EQ(y0-y1, v.getY());
	EXPECT_FLOAT_EQ(z0-z1, v.getZ());
}


TEST_F(Vector3Test, mul)
{
	const Vector3 v0(x0, y0, z0);
	const Vector3 v1(x1, y1, z1);
	const f32 f = randf();
	Vector3 v;

	// operator *=(const Vector3&)
	v = v0;
	v *= v1;
	EXPECT_FLOAT_EQ(x0*x1, v.getX());
	EXPECT_FLOAT_EQ(y0*y1, v.getY());
	EXPECT_FLOAT_EQ(z0*z1, v.getZ());

	// operator *=(f32)
	v = v0;
	v *= f;
	EXPECT_FLOAT_EQ(x0*f, v.getX());
	EXPECT_FLOAT_EQ(y0*f, v.getY());
	EXPECT_FLOAT_EQ(z0*f, v.getZ());

	// operator *(const Vector3&, const Vector3&)
	v = v0 * v1;
	EXPECT_FLOAT_EQ(x0*x1, v.getX());
	EXPECT_FLOAT_EQ(y0*y1, v.getY());
	EXPECT_FLOAT_EQ(z0*z1, v.getZ());

	// operator *(const Vector3&, f32)
	v = v0 * f;
	EXPECT_FLOAT_EQ(x0*f, v.getX());
	EXPECT_FLOAT_EQ(y0*f, v.getY());
	EXPECT_FLOAT_EQ(z0*f, v.getZ());

	// operator *(f32, const Vector3&)
	v = f * v1;
	EXPECT_FLOAT_EQ(f*x1, v.getX());
	EXPECT_FLOAT_EQ(f*y1, v.getY());
	EXPECT_FLOAT_EQ(f*z1, v.getZ());
}


TEST_F(Vector3Test, div)
{
	const Vector3 v0(x0, y0, z0);
	const Vector3 v1(x1, y1, z1);
	const f32 f = randf();
	Vector3 v;

	// operator /=(const Vector3&)
	v = v0;
	v /= v1;
	EXPECT_FLOAT_EQ(x0/x1, v.getX());
	EXPECT_FLOAT_EQ(y0/y1, v.getY());
	EXPECT_FLOAT_EQ(z0/z1, v.getZ());

	// operator /=(f32)
	v = v0;
	v /= f;
	EXPECT_FLOAT_EQ(x0/f, v.getX());
	EXPECT_FLOAT_EQ(y0/f, v.getY());
	EXPECT_FLOAT_EQ(z0/f, v.getZ());

	// operator /(const Vector3&, const Vector3&)
	v = v0 / v1;
	EXPECT_FLOAT_EQ(x0/x1, v.getX());
	EXPECT_FLOAT_EQ(y0/y1, v.getY());
	EXPECT_FLOAT_EQ(z0/z1, v.getZ());

	// operator /(const Vector3&, f32)
	v = v0 / f;
	EXPECT_FLOAT_EQ(x0/f, v.getX());
	EXPECT_FLOAT_EQ(y0/f, v.getY());
	EXPECT_FLOAT_EQ(z0/f, v.getZ());
}


TEST_F(Vector3Test, memberFunctions)
{
	const Vector3 v0(x0, y0, z0);
	const Vector3 v1(x1, y1, z1);
	const f32 f = randf();
	Vector3 v;

	// set & get
	v.set(x0, y0, z0);
	EXPECT_FLOAT_EQ(x0, v.getX());
	EXPECT_FLOAT_EQ(y0, v.getY());
	EXPECT_FLOAT_EQ(z0, v.getZ());

	// normalize
	v.set(x0, y0, z0);
	v.normalize();
	EXPECT_FLOAT_EQ(1.0f, v.getX()*v.getX() + v.getY()*v.getY() + v.getZ()*v.getZ());
	v.set(x0, y0, z0);
	v = v.getNormalize();
	EXPECT_FLOAT_EQ(1.0f, v.getX()*v.getX() + v.getY()*v.getY() + v.getZ()*v.getZ());

	// cross
	v = v0;
	v.cross(v1);
	EXPECT_FLOAT_EQ(y0*z1 - z0*y1, v.getX());
	EXPECT_FLOAT_EQ(z0*x1 - x0*z1, v.getY());
	EXPECT_FLOAT_EQ(x0*y1 - y0*x1, v.getZ());
	v = v0.getCross(v1);
	EXPECT_FLOAT_EQ(y0*z1 - z0*y1, v.getX());
	EXPECT_FLOAT_EQ(z0*x1 - x0*z1, v.getY());
	EXPECT_FLOAT_EQ(x0*y1 - y0*x1, v.getZ());

	// dot
	EXPECT_FLOAT_EQ(x0*x1 + y0*y1 + z0*z1, v0.dot(v1));

	// length
	EXPECT_FLOAT_EQ(sqrtf(x0*x0 + y0*y0 + z0*z0), v0.length());
	EXPECT_FLOAT_EQ(x0*x0 + y0*y0 + z0*z0, v0.lengthSq());
}


